#pragma once

#ifndef WinGdiWarp_h__
#define WinGdiWarp_h__

#include <Windows.h>

class WindowDC
{
public:
    WindowDC(HWND wnd)
        : _windowDC(::GetWindowDC(wnd)), _wnd(wnd)
    {};
    ~WindowDC()
    {
        ::ReleaseDC(_wnd, _windowDC);
    }
    operator HDC()
    {
        return _windowDC;
    }
    HDC operator *()
    {
        return _windowDC;
    }
private:
    HWND _wnd = nullptr;
    HDC _windowDC = nullptr;
};

class CompatibleDC
{
public:
    CompatibleDC(HDC dc)
        : _compatibleDc(::CreateCompatibleDC(dc)), _dc(dc)
    {};
    ~CompatibleDC()
    {
        ::DeleteDC(_compatibleDc);
    }
    operator HDC()
    {
        return _compatibleDc;
    }
    HDC operator *()
    {
        return _compatibleDc;
    }
private:
    HDC _dc = nullptr;
    HDC _compatibleDc = nullptr;
};

class CompatibleBitmap
{
public:
    CompatibleBitmap(HDC dc, int width, int height)
        : _compatibleBitmap(::CreateCompatibleBitmap(dc, width, height))
    {};
    ~CompatibleBitmap()
    {
        if (_used)
            unuse();
        ::DeleteObject(_compatibleBitmap);
    }
    operator HBITMAP()
    {
        return _compatibleBitmap;
    }
    HBITMAP operator *()
    {
        return _compatibleBitmap;
    }
    void use(HDC dc)
    {
        if (!_used)
        {
            _usingDC = dc;
            _orgBitmap = ::SelectObject(_usingDC, _compatibleBitmap);
            _used = true;
        }
    }
    void unuse()
    {
        if (_used)
        {
            ::SelectObject(_usingDC, _orgBitmap);
            _used = false;
        }
    }
private:
    HBITMAP _compatibleBitmap = nullptr;

    HDC _usingDC = nullptr;
    bool _used = false;
    HGDIOBJ _orgBitmap = nullptr;
};

class Rect
{
public:
    Rect(RECT r)
        : left(r.left), right(r.right), top(r.top), bottom(r.bottom)
    {}
public:
    void calcFromLRTB()
    {
        this->width = right - left;
        this->height = bottom - top;
        this->centerx = left + width / 2;
        this->centery = top + height / 2;
    }
public:
    operator RECT()
    {
        return RECT{ static_cast<LONG>(left), static_cast<LONG>(top), static_cast<LONG>(right), static_cast<LONG>(bottom) };
    }
public:
    double left, right, top, bottom;
    double width, height, centerx, centery;
};

inline Rect windowRect(HWND window)
{
    RECT r;
    ::GetWindowRect(window, &r);
    return r;
}

inline POINT cursorPos()
{
    POINT p;
    ::GetCursorPos(&p);
    return p;
}

#endif // WinGdiWarp_h__